use super::Decode;

impl<'de> Decode<'de> for u8 {
    const DECODE_MIN_LEN: usize = 1;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        if buf.len() < Self::DECODE_MIN_LEN {
            return None;
        }
        Some(buf[0])
    }
}

impl<'de> Decode<'de> for u16 {
    const DECODE_MIN_LEN: usize = 2;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        if buf.len() < Self::DECODE_MIN_LEN {
            return None;
        }
        Some(((buf[0] as u16) << 8) | (buf[1] as u16))
    }
}

impl<'de> Decode<'de> for u32 {
    const DECODE_MIN_LEN: usize = 4;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        if buf.len() < Self::DECODE_MIN_LEN {
            return None;
        }
        Some(
            ((buf[0] as u32) << 24)
                | ((buf[1] as u32) << 16)
                | ((buf[2] as u32) << 8)
                | (buf[3] as u32),
        )
    }
}

impl<'de> Decode<'de> for i8 {
    const DECODE_MIN_LEN: usize = 1;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        if buf.len() < Self::DECODE_MIN_LEN {
            return None;
        }
        Some(buf[0] as i8)
    }
}

impl<'de> Decode<'de> for i16 {
    const DECODE_MIN_LEN: usize = 2;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let v = ((buf[0] as u16) << 8) | (buf[1] as u16);
        Some(v as i16)
    }
}

impl<'de> Decode<'de> for i32 {
    const DECODE_MIN_LEN: usize = 4;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let v = ((buf[0] as u32) << 24)
            | ((buf[1] as u32) << 16)
            | ((buf[2] as u32) << 8)
            | (buf[3] as u32);

        Some(v as i32)
    }
}

impl<'de> Decode<'de> for () {
    const DECODE_MIN_LEN: usize = 0;
    fn from_bytes(_buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        Some(())
    }
}

impl<'de> Decode<'de> for &'de [u8] {
    const DECODE_MIN_LEN: usize = 1;
    fn from_bytes(buf: &'de [u8]) -> Option<Self>
    where
        Self: Sized,
    {
        let buf_len = buf.len();
        if buf_len < 1 {
            return None;
        }
        let len = buf[0] as usize;
        if buf_len < (1 + len) {
            return None;
        }
        Some(&buf[1..(1 + len)])
    }
}
